package com.yuandian.management.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yuandian.api.business_monitor.po.SearchParams;
import com.yuandian.api.customer_perception.po.OperatorOverviewParams;
import com.yuandian.api.management.entity.ConfArea;
import com.yuandian.api.management.entity.ConfBusinessHall;
import com.yuandian.bpm.common.core.util.R;
import com.yuandian.bpm.common.security.util.SecurityUtils;
import com.yuandian.management.mapper.ConfBusinessHallMapper;
import com.yuandian.management.service.ConfAreaService;
import com.yuandian.management.service.ConfBusinessHallService;
import com.yuandian.management.vo.BusinessHallExcelVo;
import com.yuandian.management.vo.SearchOptionVo;
import com.yuandian.utils.ListUtils;
import com.yuandian.utils.poi.BatchDataResult;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 营业厅配置表-Service实现
 * @author zfsn
 * @date 2023-3-28
 */
@Service
public class ConfBusinessHallServiceImpl extends ServiceImpl<ConfBusinessHallMapper, ConfBusinessHall>
		implements ConfBusinessHallService {

	@Autowired
	ConfBusinessHallMapper confBusinessHallMapper;

	@Autowired
	ConfAreaService confAreaService;

	@Override
	public ConfBusinessHall getById(Serializable id) {
		ConfBusinessHall confBusinessHall = super.getById(id);
		LambdaQueryWrapper<ConfArea> queryWrapper = Wrappers.lambdaQuery();
		queryWrapper.eq(ConfArea::getCode, confBusinessHall.getAreaCode());
		ConfArea confArea = confAreaService.getOne(queryWrapper);
		confBusinessHall.setParentAreaCode(String.valueOf(confArea.getParentId()));
		return confBusinessHall;
	}


	/**
	 * 新增数据
	 *
	 * @param confBusinessHall 实例对象
	 * @return 通用返回对象
	 */
	@Override
	public R<String> saveBusinessHall(ConfBusinessHall confBusinessHall) {
		if(checkBusinessHallNumDuplicates(confBusinessHall)){
			return R.failed("营业厅编码存在重复");
		}
		confBusinessHall.setCreateBy(SecurityUtils.getUser().getName());
		super.save(confBusinessHall);
		return R.ok("营业厅信息添加成功");
	}

	/**
	 * 判断营业厅编码是否重复
	 * @param confBusinessHall
	 * @return
	 */
	private boolean checkBusinessHallNumDuplicates(ConfBusinessHall confBusinessHall) {
		LambdaQueryWrapper<ConfBusinessHall> queryWrapper = Wrappers.lambdaQuery();
		queryWrapper.eq(ConfBusinessHall::getNum, confBusinessHall.getNum());
		if (confBusinessHall.getId() != null) {
			queryWrapper.ne(ConfBusinessHall::getId, confBusinessHall.getId());
		}
		return super.count(queryWrapper) > 0;
	}

	/**
	 * 通过主键更新数据
	 *
	 * @param confBusinessHall 实例对象
	 * @return 通用返回对象
	 */
	@Override
	public R<String> updateBusinessHallById(ConfBusinessHall confBusinessHall) {
		if(checkBusinessHallNumDuplicates(confBusinessHall)){
			return R.failed("营业厅编码存在重复");
		}
		confBusinessHall.setUpdateBy(SecurityUtils.getUser().getName());
		super.updateById(confBusinessHall);
		return R.ok("营业厅信息修改成功");
	}

	/**
	 * 分页查询
	 *
	 * @param confBusinessHall 筛选条件
	 * @return 通用返回对象
	 */
	@Override
	public Page<ConfBusinessHall> listPage(ConfBusinessHall confBusinessHall) {
		return confBusinessHallMapper.listPage(new Page<>(confBusinessHall.getPageNum(), confBusinessHall.getPageSize()),confBusinessHall);
	}

	/**
	 * 指定地区下的营业厅
	 *
	 * @param searchParams 主键
	 * @return 通用返回对象
	 */
	@Override
	public List<Map<String, String>> getBusinessHall(SearchParams searchParams) {
		return confBusinessHallMapper.getBusinessHall(searchParams);
	}

	/**
	 * 查询营业厅信息并装换成 Map<营业厅编码， 营业厅名称>
	 *
	 * @param searchParams 业务编码集合
	 * @return 搜索选项vo对象集合
	 */
	@Override
	public Map<String, String> getBusinessHallMap(SearchParams searchParams) {
		if (Objects.isNull(searchParams)) {
			searchParams = new SearchParams();
		}
		Map<String,String> map = new HashMap<>();
		List<Map<String, String>> list = confBusinessHallMapper.getBusinessHall(searchParams);
		if (ListUtils.isNotNull(list)) {
			for (Map<String, String> voMap : list) {
				if(ObjectUtil.isNotEmpty(voMap)){
					map.put(voMap.get("businessHallId"), voMap.get("label"));
				}
			}
		}
		return map;
	}

	/**
	 * 根据营业厅名称列表获取营业厅Id列表
	 *
	 * @param businessHallName
	 * @return 搜索选项vo对象集合
	 */
	@Override
	public List<String> getBusinessHallIdListByHallNameList(String businessHallName) {
		// 根据单位名称获取单位编号
		List<ConfBusinessHall> confBusinessHalls = confBusinessHallMapper.selectList(new LambdaQueryWrapper<ConfBusinessHall>().
				like(Objects.nonNull(businessHallName), ConfBusinessHall::getName, businessHallName));

		return confBusinessHalls.stream().map(ConfBusinessHall::getNum).distinct().collect(Collectors.toList());
	}

	/**
	 * 保存导入的数据
	 *
	 * @param dataList
	 */
	@Override
	public void saveBatchExcelData(List<BusinessHallExcelVo> dataList) {
		if(!CollectionUtils.isEmpty(dataList)) {
			List<ConfBusinessHall> businessHallList = new ArrayList<>();

			for (BusinessHallExcelVo excelVo : dataList) {
				ConfBusinessHall businessHall = new ConfBusinessHall();
				BeanUtils.copyProperties(excelVo, businessHall);
				businessHall.setNum(excelVo.getNum());
				businessHall.setName(excelVo.getName());
				businessHall.setAreaCode(excelVo.getRegion());

				businessHallList.add(businessHall);
			}
			super.saveBatch(businessHallList);
		}
	}

	/**
	 * 入库前-批量校验数据
	 *
	 * @param dataList
	 * @return
	 */
	@Override
	public BatchDataResult<BusinessHallExcelVo> checkBatchExcelData(List<BusinessHallExcelVo> dataList) {
		//查出所有正确格式的省市名组合,并放入集合
		List<ConfBusinessHall> areaAll = confBusinessHallMapper.queryRegionAndAreaId();
		List<BusinessHallExcelVo> successList = new ArrayList<>();
		List<BusinessHallExcelVo> failList = new ArrayList<>();
		if(!CollectionUtils.isEmpty(dataList)) {
			//用areaMap存下地名和id,其中地名为键,id是String格式
			Map<String,String> areaMap = areaAll.stream().collect(Collectors.toMap(ConfBusinessHall::getFullRegionName,
					hall -> String.valueOf(hall.getId())));

			Set<String> existBusinessHallNumSet = confBusinessHallMapper.selectList(new LambdaQueryWrapper<>())
					.stream().map(ConfBusinessHall::getNum).collect(Collectors.toSet());
			for (BusinessHallExcelVo businessHallExcelVo : dataList) {
				//getOrDefault:传入一个key,如果key存在则返回key对应的value,如果key不存在,则返回默认值
				//如果区域存在,则返回该区域,如果区域不存在,则返回空
				businessHallExcelVo.setRegion(areaMap.get(businessHallExcelVo.getRegion()));
				//对营业厅编号进行去重处理
				if (!existBusinessHallNumSet.contains(businessHallExcelVo.getNum())){
					successList.add(businessHallExcelVo);
				}else {
					failList.add(businessHallExcelVo);
				}
			}
		}
		return new BatchDataResult<>(true, successList,failList);
	}

	/**
	 * 解析阶段-校验数据
	 *
	 * @param data
	 * @return
	 */
	@Override
	public boolean checkExcelData(BusinessHallExcelVo data) {
		try {
			Field[] fields = data.getClass().getDeclaredFields();
			for (Field field : fields) {
				field.setAccessible(true);
				if (field.get(data) == null) {
					return false;
				}
			}
		} catch (IllegalAccessException e) {
			log.error(e.getMessage(), e);
			return false;
		}
		return true;
	}

	/**
	 * 查询指定地区下的营业厅
	 * @param params 请求参数
	 * @return 查询指定地区下的营业厅列表
	 */
	@Override
	public List<SearchOptionVo> queryBusinessHall(@Param("params") OperatorOverviewParams params){
		return this.baseMapper.queryBusinessHall(params);
	}

	/**
	 * 根据营业厅编码查询营业厅名
	 * @return
	 */
	@Override
	public R<String> queryBusinessHallNameById(String businessHallId) {
		ConfBusinessHall one = this.lambdaQuery().eq(ConfBusinessHall::getNum, businessHallId).last("limit 1").one();
		if (one == null){
			return R.ok("");
		}
		return R.ok(one.getName());
	}
}
